/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package it.polimi.meteocal.control;

import it.polimi.meteocal.entity.Event;
import it.polimi.meteocal.entity.Message;
import it.polimi.meteocal.entity.MessageList;
import it.polimi.meteocal.entity.MessageListPK;
import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

/**
 *
 * @author paolo
 */
@Stateless
public class MessageManager {

    @PersistenceContext
    private EntityManager em;
    @EJB
    private UserManager um;

    /**
     *
     * @return all the message of the logged user
     */
    public ArrayList<Message> getMessage() {
        System.out.println("******GETMESSAGE*******");
        em.getEntityManagerFactory().getCache().evictAll();
        ArrayList<Message> messages = new ArrayList<>();
        for (MessageList messageListCollection : um.getLoggedUser().getMessageListCollection()) {
            messages.add(messageListCollection.getMessage());
        }
        messages = sortMessagebyTimestamp(messages);
        return messages;
    }

    public ArrayList<Message> sortMessagebyTimestamp(ArrayList<Message> messages) {
        //Message [] mes = (Message[]) messages.toArray();
        Message[] mes = new Message[messages.size()];
        for (int i = 0; i < messages.size(); i++) {
            mes[i] = messages.get(i);
        }
        mergeSort(mes);
        ArrayList<Message> result = new ArrayList<>();
        for (Message m : mes) {
            result.add(m);
        }
        return (result);
    }

    private static void mergeSort(Message[] a, Message[] vectorTemp, int left, int right) {
        if (left < right) {
            int center = (left + right) / 2;
            mergeSort(a, vectorTemp, left, center);
            mergeSort(a, vectorTemp, center + 1, right);
            merge(a, vectorTemp, left, center + 1, right);
        }
    }

    public static void mergeSort(Message[] a) {
        Message vectorTemp[];
        vectorTemp = new Message[a.length];
        mergeSort(a, vectorTemp, 0, a.length - 1);
    }

    private static void merge(Message[] a, Message[] vectorAux, int posLeft, int posRight, int posEnd) {
        int endLeft = posRight - 1;
        int posAux = posLeft;
        int numElemen = posEnd - posLeft + 1;

        while (posLeft <= endLeft && posRight <= posEnd) {
            if ((a[posLeft].getPubblication()).before(a[posRight].getPubblication())) {
                vectorAux[posAux++] = a[posLeft++];
            } else {
                vectorAux[posAux++] = a[posRight++];
            }
        }

        while (posLeft <= endLeft) {
            vectorAux[posAux++] = a[posLeft++];
        }

        while (posRight <= posEnd) {
            vectorAux[posAux++] = a[posRight++];
        }

        for (int i = 0; i < numElemen; i++, posEnd--) {
            a[posEnd] = vectorAux[posEnd];
        }
    }

    /**
     * create a message and persist it into the database
     *
     * @param event the event reletaded to the message
     * @param type the type of the message
     * @return the message created
     */
    public Message createMessage(Event event, int type) {
        System.out.println("**********CREATE MESSAGE************");
        Message message = new Message();
        message.setEvent(event);
        GregorianCalendar cal = new GregorianCalendar();
        Date d = cal.getTime();
        GregorianCalendar date = new GregorianCalendar();
        date.setTime(d);
        message.setPubblication(date);
        message.setType(type);
        setText(message);
        em.persist(message);
        em.flush();
        return message;
    }

    /**
     * create a message and persist it into the database
     *
     * @param event the event reletaded to the message
     * @param type the type of the message
     * @param text the proposed good day for the the event
     * @return the message created
     */
    public Message createMessage(Event event, int type, String text) {
        System.out.println("**********CREATE MESSAGE************");
        Message message = new Message();
        message.setEvent(event);
        GregorianCalendar cal = new GregorianCalendar();
        Date d = cal.getTime();
        GregorianCalendar date = new GregorianCalendar();
        date.setTime(d);
        message.setPubblication(date);
        message.setType(type);
        setText(message, text);
        em.persist(message);
        em.flush();
        return message;
    }

    /**
     * add the message tothe list of messages of all the user in the list and
     * persist to the data base
     *
     * @param event
     * @param invitedUsers the list of the user to send the message
     * @param message
     */
    public void addInvitedMessage(Event event, List<String> invitedUsers, Message message) {
        for (String invitedUser : invitedUsers) {
            MessageListPK messageListPK = new MessageListPK();
            messageListPK.setMessage(message.getMessageID());
            MessageList messageList = new MessageList();
            messageListPK.setUser(invitedUser);
            messageList.setMessageListPK(messageListPK);
            messageList.setPending(Boolean.TRUE);
            em.persist(messageList);
            em.flush();
        }
    }

    /**
     * remove a message from the list of the messages of the logged user
     *
     * @param selectedMessage
     */
    public void remove(Message selectedMessage) {
        Message m = em.find(Message.class, selectedMessage.getMessageID());
        MessageListPK messageListPK = new MessageListPK();
        messageListPK.setMessage(m.getMessageID());
        messageListPK.setUser(um.getLoggedUser().getEmail());
        MessageList toDelete = em.find(MessageList.class, messageListPK);
        em.remove(toDelete);
        em.flush();
    }

    /**
     * chek if the logged user as pending messages
     *
     * @return true if exist at leat on pending message,false otherwise
     */
    public Boolean checkPending() {
        for (MessageList messageListCollection : um.getLoggedUser().getMessageListCollection()) {
            if (messageListCollection.getPending()) {
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;
    }

    /**
     * set all the messages in the list of the logged user message as already
     * readed
     */
    public void setPending() {
        for (MessageList messageListCollection : um.getLoggedUser().getMessageListCollection()) {
            if (messageListCollection.getPending()) {
                messageListCollection.setPending(Boolean.FALSE);
            }
        }
    }

    /**
     * set the text of the message
     *
     * @param selectedmessage
     */
    public void setText(Message selectedmessage) {
        String s;
        switch (selectedmessage.getType()) {
            case 0:
                s = "the event " + selectedmessage.getEvent().getName() + " has been deleted";
                break;
            case 2:
                s = "you have been invited to the event " + selectedmessage.getEvent().getName() + ". \n Would you participate to it?";
                break;
            case 1:
                s = "the event " + selectedmessage.getEvent().getName() + " has been modified. \n Would you go to check?";
                break;
            case 3:
                s = "for the event " + selectedmessage.getEvent().getName() + " of tomorrow there will be bad condition";
                break;
            default:
                s = "This message should never be sent";
        }
        selectedmessage.setText(s);
    }

    /**
     * set the text of the message with the proposed good day
     *
     * @param selectedmessage
     * @param text
     */
    private void setText(Message selectedmessage, String text) {
        String s;
        switch (selectedmessage.getType()) {
            case 4:
                s = "for the event " + selectedmessage.getEvent().getName() + " of " + selectedmessage.getEvent().getStartDate().getTime() + " there will be bad condition. \n Would you can change with " + text + " ?";
                break;
            default:
                s = "This message should never be sent";
        }
        selectedmessage.setText(s);
    }
}
